package com.pap.base.controller;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.springframework.web.bind.annotation.*;

import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.pap.base.entity.PapBaseEntity;
import com.pap.base.exception.IdValidationException;
import com.pap.base.service.IPapBaseService;
import com.pap.base.util.date.DateUtils;
import com.pap.base.util.jackson.JacksonUtilss;
import com.pap.base.util.string.StringUtilss;
import com.pap.obj.vo.page.Page;
import com.pap.obj.vo.response.ResponseVO;

public abstract class BaseController<E extends PapBaseEntity, S extends IPapBaseService<E>> {

	protected S service;

	public abstract void setService(S service);

	/**
	 * 数据查询
	 * @param clientLicenseId
	 * @param loginUserId
	 * @param id
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	@RequestMapping(value = "/{id}", method = {RequestMethod.GET})
	public ResponseVO<E> selectById(@RequestHeader(value = "clientLicenseId", defaultValue = "-1") String clientLicenseId,
			@RequestHeader(value = "loginUserId", defaultValue = "-1") String loginUserId,
			@PathVariable String id) throws Exception {

		if (null == id) {
			return null;
		}

		E e = service.selectByPrimaryKey(id);
		return ResponseVO.successdata(e);
	}

	/**
	 * 数据添加
	 * @param clientLicenseId
	 * @param loginUserId
	 * @param addJSON
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	@RequestMapping(value = "/add", method = {RequestMethod.POST})
	public ResponseVO<E> add(@RequestHeader(value = "clientLicenseId", defaultValue = "-1") String clientLicenseId,
			@RequestHeader(value = "loginUserId", defaultValue = "-1") String loginUserId,
			@RequestParam(value = "addJSON", required = true) String addJSON) throws Exception {
		Class<E> entityClass = (Class<E>) ((ParameterizedType) getClass().getGenericSuperclass())
				.getActualTypeArguments()[0];

		ObjectMapper objectMapper = JacksonUtilss.getObjectMapper();
		E e = objectMapper.readValue(addJSON, entityClass);
		if(StringUtilss.isEmpty(e.getId())) {
			e.setId(UUID.randomUUID().toString());
		}
		e.setCreateIp("0.0.0.0");
		e.setCreateTime(DateUtils.getCurrDateTimeStr());
		e.setCreateUser(loginUserId);
		e.setClientLicenseId(clientLicenseId);

		int operationInt = service.insertSelective(e);
		return ResponseVO.successdata(operationInt);
	}

	/**
	 * 数据更新
	 * @param clientLicenseId
	 * @param loginUserId
	 * @param updateJSON
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	@RequestMapping(value = "/update", method = {RequestMethod.POST})
	public ResponseVO<E> update(@RequestHeader(value = "clientLicenseId", defaultValue = "-1") String clientLicenseId,
			@RequestHeader(value = "loginUserId", defaultValue = "-1") String loginUserId,
			@RequestParam(value = "updateJSON", required = true) String updateJSON) throws Exception {

		Class<E> entityClass = (Class<E>) ((ParameterizedType) getClass().getGenericSuperclass())
				.getActualTypeArguments()[0];

		ObjectMapper objectMapper = JacksonUtilss.getObjectMapper();
		E e = objectMapper.readValue(updateJSON, entityClass);
		
		e.setModifyIp("0.0.0.0");
		e.setModifyTime(DateUtils.getCurrDateTimeStr());
		e.setModifyUser(loginUserId);

		if (null == e.getId()) {
			// id不存在
			throw new IdValidationException("更新操作，不存在此项数据!");
		}

		int operationInt = service.updateByPrimaryKeySelective(e);
		return ResponseVO.successdata(operationInt);
	}
	
	/**
	 * 删除操作
	 * @param clientLicenseId
	 * @param loginUserId
	 * @param deleteJSON
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	@RequestMapping(value = "/delete", method = {RequestMethod.POST})
	public ResponseVO<E> delete(@RequestHeader(value = "clientLicenseId", defaultValue = "-1") String clientLicenseId,
			@RequestHeader(value = "loginUserId", defaultValue = "-1") String loginUserId,
			@RequestParam(value = "deleteJSON", required = true) String deleteJSON) throws Exception {

		Class<E> entityClass = (Class<E>) ((ParameterizedType) getClass().getGenericSuperclass())
				.getActualTypeArguments()[0];

		ObjectMapper objectMapper = JacksonUtilss.getObjectMapper();
		E e = objectMapper.readValue(deleteJSON, entityClass);
		
		if (null == e.getId()) {
			// id不存在
			throw new IdValidationException("删除操作，不存在此项数据!");
		}

		int operationInt = service.deleteByPrimaryKey(e.getId());
		return ResponseVO.successdata(operationInt);
	}

	/**
	 * 查询条件
	 * @param clientLicenseId
	 * @param loginUserId
	 * @param queryJSON
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	@RequestMapping(value = "/query", method = {RequestMethod.GET})
	public ResponseVO<E> query(@RequestHeader(value = "clientLicenseId", defaultValue = "-1") String clientLicenseId,
			@RequestHeader(value = "loginUserId", defaultValue = "-1") String loginUserId,
			@RequestParam(value = "queryJSON", required = true) String queryJSON) throws Exception {

		ObjectMapper mapper = JacksonUtilss.getObjectMapper();
		Map<Object, Object> queryMap = mapper.readValue(queryJSON, Map.class);
		queryMap.put("clientLicenseId", clientLicenseId);
		
		List<E> operationList = service.selectListByMap(queryMap);
		return ResponseVO.successdatas(operationList, null);
	}
	
	/**
	 * 查询条件并且分页
	 * @param clientLicenseId
	 * @param loginUserId
	 * @param queryJSON
	 * @param pageJSON
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	@RequestMapping(value = "/querypage", method = {RequestMethod.GET})
	public ResponseVO<E> queryPage(@RequestHeader(value = "clientLicenseId", defaultValue = "-1") String clientLicenseId,
			@RequestHeader(value = "loginUserId", defaultValue = "-1") String loginUserId,
			@RequestParam(value = "queryJSON", required = true) String queryJSON,
			@RequestParam(value = "pageJSON", required = true) String pageJSON) throws Exception {

		ObjectMapper mapper = JacksonUtilss.getObjectMapper();
		
		Map<Object, Object> searchMap = new HashMap<Object, Object>();
		
		Map<Object, Object> queryMap = mapper.readValue(queryJSON, Map.class);
		Map<Object, Object> pageMap = mapper.readValue(pageJSON, Map.class);
		
		searchMap.putAll(queryMap);
		
		Page page = null;
		if(pageMap != null && !pageMap.isEmpty() && pageMap.containsKey("page") && pageMap.containsKey("rows")) {
			page = new Page(pageMap.get("page").toString(), pageMap.get("rows").toString(), 0);
			searchMap.put("page", page);
		} else {
			page = new Page("1", "10", 0);
		}
		searchMap.put("clientLicenseId", clientLicenseId);
		
		List<E> operationList =  service.selectListByMap(searchMap);
		int count = service.selectCountByMap(searchMap);
		page = new Page(page.getCurrent() + "", page.getLength() + "", count);
		
		return ResponseVO.successdatas(operationList, page);
	}
	
	@SuppressWarnings("unchecked")
	@RequestMapping(value = "/flat", method = {RequestMethod.GET})
	public ResponseVO<E> flat(@RequestHeader(value = "clientLicenseId", defaultValue = "-1") String clientLicenseId,
			@RequestHeader(value = "loginUserId", defaultValue = "-1") String loginUserId) throws Exception {

		Map<Object, Object> queryMap = new HashMap<Object, Object>();
		queryMap.put("clientLicenseId", clientLicenseId);
		
		List<E> operationList = service.selectListByMap(queryMap);
		return ResponseVO.successdatas(operationList, null);
	}
	
	@SuppressWarnings("unchecked")
	@RequestMapping(value = "/enums", method = {RequestMethod.GET})
	public ResponseVO<E> enums(@RequestParam(value = "clazzStr", required = true) String clazzStr) throws Exception {
		List<Map<String, Object>> enumsList = printEnumValues(clazzStr);
		return ResponseVO.successdatas(enumsList, null);
	}

	public static List<Map<String, Object>> printEnumValues(String clazzNamePath) {
		List<Map<String, Object>> returnList = new ArrayList<Map<String, Object>>();
		try { 
			Class c = Class.forName(clazzNamePath);
			if (c.isEnum()) {
				try {
					Object[] objs = c.getEnumConstants();
					for (Object obj : objs) {
						Method m = obj.getClass().getDeclaredMethod("values", null);
						Object[] result = (Object[]) m.invoke(obj, null);
						List list = Arrays.asList(result);
						Iterator it = list.iterator();
						while (it.hasNext()) {
							Object objOne = it.next();
							Field code = objOne.getClass().getDeclaredField("key");
							Field codeDesc = objOne.getClass().getDeclaredField("value");
							Field priority = null;
							try {
								priority = objOne.getClass().getDeclaredField("priority");
							} catch (Exception e) {
								priority = null;
							}
							code.setAccessible(true);
							codeDesc.setAccessible(true);
							if (priority != null) {
								priority.setAccessible(true);
							}
							System.out.println(code.getName() + ":" + code.get(objOne) + "," + codeDesc.getName() + ":"
									+ codeDesc.get(objOne));
							Map<String, Object> fieldMapTemp = new HashMap<String, Object>(16);
							fieldMapTemp.put(code.getName(), code.get(objOne));
							fieldMapTemp.put(codeDesc.getName(), codeDesc.get(objOne));
							fieldMapTemp.put("enumvalue", objOne);
							returnList.add(fieldMapTemp);
						}
						break;
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		} catch (ClassNotFoundException e1) {
			e1.printStackTrace();
		}
		return returnList;
	}
	
    /**   
     * 获取泛型的Collection Type  
     * @param collectionClass 泛型的Collection   
     * @param elementClasses 元素类   
     * @return JavaType Java类型   
     * @since 1.0   
     */   
	public static JavaType getCollectionType(ObjectMapper mapper, Class<?> collectionClass, Class<?>... elementClasses) {   
		return mapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);   
	}
}
